#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>

//Maxima inclinacion de las ruedas para cruzar
#define ANG_RUEDAS 30;
//Conversion de Radianes a Grados
#define R2G 57.2957795

//Texturas del Mapa
GLuint asfalto[1];
GLuint edificio[2];
GLuint pared[1];
GLuint madera[1];

//Contador de bombas
GLint b;
//Tiempo de salto
GLdouble t;
//Items
GLint amno,vida;

//Imagenes para las texturas
typedef struct {
    GLuint sizeX;
    GLuint sizeY;
    char *data;
} Imagen;

//Linea que define una pared
typedef struct {
    //Posicion
    GLdouble xi,xf;
    GLdouble zi,zf;
    //Altura
    GLdouble a;
    //Es horizontal
    GLint hor;
} Linea;

//Edificio
typedef struct {
    //Posicion
    GLdouble xi,xf;
    GLdouble zi,zf;
} Edif;

//Rampa
typedef struct {
    //Posicion
    GLdouble xi,xf;
    GLdouble zi,zf;
    //Alineacion
    GLint normal;
} Rampa;

//Nodo del grafo de caminos
typedef struct {
    //Lados
    GLdouble x1,z1;
    GLdouble x2,z2;
    GLdouble x3,z3;
    //Centro
    GLdouble x, z;
    //Vecinos
    GLint v1,v2,v3;
    //Fue visitado
    GLint visitado;
    //Alguien dejo rastro
    GLint yo_aceite;
    GLint com_aceite;
    //Tiempo en alcanzar el siguiente
    GLint time;
} Nodo;

//Iteraciones del A*
GLint pasos;
//Variables que guardan las estructuras de los objetos fijos del mapa
GLint nr;
Linea* rectas;
GLint nramp;
Rampa* rampas;
GLint nedif;
Edif* edifs;
//Grafo de Caminos
GLint nn;
Nodo* nodos;

//Carro
typedef struct {
    // posicion y direccion de vision
    GLdouble x, y, z;
    GLdouble vision;
    GLdouble ang_ruedas;
    // Velocidad (dirección y magnitud)
    GLdouble v_mag;     
    // Velocidad Angular
    GLdouble a_mag;
    // velocidad agregada por una colision.
    GLdouble vc_dir,vc_mag;
    // Indica si el carro esta acelerando o no
    GLint acelera;
    // Cuanto tiempo lleva acelerando
    GLint time_units;
    // Indica la velocidad en el eje y
    GLdouble vy;
    // angulo de su cañon
    GLdouble ang_canon;
    GLint anim_canon;
    // Cuantas balas le quedan
    GLint balas;
    // cuantas vidas le quedan
    GLint vidas;
    // Indica si la bomba le ha pegado
    GLint hit;
    // Indica si esta saltando
    GLint salta;
    // nodo en el que estoy
    GLint nodo;
    // nodo target
    GLint nodot;
    // nodo siguiente
    GLint nodosig;
    // si IDAstar termino
    GLint llegue;
} Car;

//Estado usado para la toma de decisiones
typedef struct {
    // indentificador del estado
    GLint id;
    // indice de la bomba mas cercana
    GLint bomb;
    // apuntador al carro enemigo
    Car* car;
}Estado;

//Estado actual del carro
Estado state;

//Bomba
typedef struct {
    // posicion de la bomba en el espacio
    GLdouble x, y, z;
    // componentes de la velocidad (direccion y magnitud)
    GLdouble v_dir, v_mag;
    // direccion en la que se mueve la bomba (en el plano x,z)
    GLdouble m_dir;
    // tiempo
    GLint time_units;
    GLint bajando;
    GLint blow;
    // Indica si le pego a un carro
    GLint hit;
    GLint side;
    // lugar donde llegará
    GLdouble tx,tz;
    // quien disparo la bomba 1=yo 0=com
    GLint quien;
} Bomb;

//Rastro de aceite
typedef struct {
    // Posicion y Tamaño de las gotas
    GLdouble aceiteXZ[200][3];
    // Numero de gotas
    GLint gotaN;
    // Gota mas antigua?
    GLint gotaP;
    // Si excedi el tamaño del arreglo
    GLint vuelta;
} OilTrace;

//Metodos implementados en car_lib.c
void construirCarro(GLdouble,GLdouble,GLfloat,GLfloat,GLfloat,GLint);

void decide(Car*,Bomb**,OilTrace*);

void seek(Car*,int);

void flee(Car*,GLdouble,GLdouble,GLdouble);

void wander(Car*);

void aim(Car*,Car*,Bomb**);

void dispara(Car*,Bomb**,GLint);

void update(Car*,Car*);

int colisiona(GLdouble,GLdouble,GLdouble,Car*);

void newPos(GLdouble*,GLdouble*,GLdouble,GLdouble);

void salta(Car*);

void gravedad(Car*);

void updateB(Bomb*);

void explota(Car*,Bomb*);

void construirBomba(GLfloat,GLfloat,GLfloat,GLdouble);

Bomb* crearBomba(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLint,GLint);

void endPoint(Bomb*);

void dibujaExplosion(GLint);

void cargarTextura();

void setCar(Car*,GLdouble,GLdouble);

void gameStats(Car*,Car*,GLint*);

void dibujaVel(GLdouble,GLint);

void construirEdificio();

void construirPared();

void construirMurito();

void construirRampa();

void cargarMapa(char*);

int enNodo(GLdouble,GLdouble,Nodo*);

void haciaDonde(Car*);

int whereIs(GLdouble,GLdouble);

void rastroAceite(Car*,Car*,OilTrace*,OilTrace*);

void setItems();

void dibujaCruz();
